﻿using System.Collections.Generic;
using System.Linq;
using AccelerateSensor.Model.Gateway;
using AccelerateSensor.Model.Node;
using AccelerateSensor.SocketServer;

namespace AccelerateSensor.Service
{
    internal class DataHelper
    {
        private readonly Dictionary<string, GatewayInfo> _gatewayInfoDict;
        private readonly IDataObserver _dataObserver;

        public DataHelper(IDataObserver dataObserver)
        {
            _gatewayInfoDict = new Dictionary<string, GatewayInfo>();
            _dataObserver = dataObserver;
        }

        public void Init(SocketServerManager manager)
        {
            manager.ReceiveGatewayInfoEvent += OnReceiveGatewayInfo;
            manager.ReceiveNodeInfoEvent += OnReceiveNodeInfo;
            manager.ReceiveNodeDataEvent += OnReceiveNodeData;
        }

        public void UnInit(SocketServerManager manager)
        {
            manager.ReceiveGatewayInfoEvent -= OnReceiveGatewayInfo;
            manager.ReceiveNodeInfoEvent -= OnReceiveNodeInfo;
            manager.ReceiveNodeDataEvent -= OnReceiveNodeData;
        }

        public List<GatewayInfo> GetGatewayList()
        {
            var list = new List<GatewayInfo>();
            lock (_gatewayInfoDict)
            {
                list.AddRange(_gatewayInfoDict.Values);
            }

            return list;
        }

        private void OnReceiveGatewayInfo(GatewayInfo info)
        {
            if (info == null || string.IsNullOrWhiteSpace(info.Uuid))
            {
                return;
            }

            lock (_gatewayInfoDict)
            {
                if (!_gatewayInfoDict.ContainsKey(info.Uuid))
                {
                    _gatewayInfoDict.Add(info.Uuid, info);
                }
                else
                {
                    _gatewayInfoDict[info.Uuid].UpdateInfo(info);
                }
            }

            _dataObserver?.GatewayInfoChanged(info);
        }

        private void OnReceiveNodeInfo(NodeInfo info)
        {
            if (info == null || string.IsNullOrWhiteSpace(info.Uuid) ||
                string.IsNullOrWhiteSpace(info.GatewayUuid))
            {
                return;
            }

            lock (_gatewayInfoDict)
            {
                if (!_gatewayInfoDict.ContainsKey(info.GatewayUuid))
                {
                    return;
                }

                var gateway = _gatewayInfoDict[info.GatewayUuid];
                var nodeInfo = gateway.NodeList.FirstOrDefault(t => info.Uuid.Equals(t.Uuid));
                if (nodeInfo == null)
                {
                    gateway.NodeList.Add(info);
                }
                else
                {
                    nodeInfo.UpdateInfo(info);
                }
            }

            _dataObserver.NodeInfoChanged(info);
        }

        private void OnReceiveNodeData(NodeData data)
        {
            if (data == null || string.IsNullOrWhiteSpace(data.NodeUuid))
            {
                return;
            }

            lock (_gatewayInfoDict)
            {
                NodeInfo nodeInfo = null;
                foreach (var gateway in _gatewayInfoDict.Values)
                {
                    nodeInfo = gateway.NodeList.FirstOrDefault(t => data.NodeUuid.Equals(t.Uuid));
                    if (nodeInfo != null)
                    {
                        break;
                    }
                }

                if (nodeInfo == null)
                {
                    return;
                }

                nodeInfo.UpdateData(data);
            }

            _dataObserver.NodeDataChanged(data);
        }
    }
}
